package com.vegetable.modules.service.inbound.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vegetable.common.constant.CommonConstant;
import com.vegetable.common.utils.Constant;
import com.vegetable.common.utils.PageUtils;
import com.vegetable.common.utils.Query;
import com.vegetable.common.utils.R;
import com.vegetable.common.base.BaseEntity;
import com.vegetable.modules.entity.baseData.*;
import com.vegetable.modules.entity.finance.po.ADCanPayPO;
import com.vegetable.modules.entity.inbound.AgentDelivery;
import com.vegetable.modules.entity.inbound.AgentDeliveryDetail;
import com.vegetable.modules.entity.inbound.AgentDeliveryDetailPack;
import com.vegetable.modules.entity.inbound.OrderCost;
import com.vegetable.modules.entity.inbound.export.AgentDeliveryImport;
import com.vegetable.modules.entity.inbound.po.AgentDeliverySequencePO;
import com.vegetable.modules.entity.outbound.SalesOrderTransmit;
import com.vegetable.modules.entity.stock.Stock;
import com.vegetable.modules.entity.stock.po.StockUpdatePO;
import com.vegetable.modules.entity.stock.to.StockFlowDTO;
import com.vegetable.modules.mapper.inbound.AgentDeliveryMapper;
import com.vegetable.modules.service.baseData.*;
import com.vegetable.modules.service.inbound.*;
import com.vegetable.modules.service.outbound.ISalesOrderTransmitService;
import com.vegetable.modules.service.stock.IStockFlowService;
import com.vegetable.modules.service.stock.IStockService;
import com.vegetable.modules.vo.AgentDeliveryDetailVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 入库-代办交货 服务实现类
 * </p>
 *
 * @author wangruijie
 * @since 2024-03-07
 */
@Slf4j
@Service
public class AgentDeliveryServiceImpl extends ServiceImpl<AgentDeliveryMapper, AgentDelivery> implements IAgentDeliveryService {

    // 订单费用
    @Resource
    private IOrderCostService orderCostService;
    // 订单商品
    @Resource
    private IAgentDeliveryDetailService deliveryDetailService;
    // 订单商品包装
    @Resource
    private IAgentDeliveryDetailPackService detailPackService;
    // 产地商品
    @Resource
    private IProductsService productsService;
    // 库存表
    @Resource
    private IStockService stockService;
    // 通讯录
    @Resource
    private IAddressBookService addressBookService;
    // 往来明细
    @Resource
    private IAccountDetailsService accountDetailsService;
    // 商品规格
    @Resource
    private IProductSpecService specService;
    // 入库库存服务
    @Resource
    private IInboundStockService inboundStockService;

    // 销售订货任务下达表
    @Resource
    private ISalesOrderTransmitService transmitService;

    @Resource
    private IStockFlowService stockFlowService;

    @Resource
    private IProductCostClauseService iProductCostClauseService;

    @Resource
    private IAddressBookService iAddressBookService;

    @Override
    public IStockService getStockService() {
        return stockService;
    }

    /**
     * 入库代办交货列表查询
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String docNo = (String)params.get("docNo");
        String state = (String)params.get("state");
        Object regionId = params.get("regionId");
        String startTime = (String)params.get("startTime");
        String endTime = (String)params.get("endTime");
        // 结账状态
        String checkout = (String)params.get("checkout");
        Integer checkout_int = null;
        if (StringUtils.isNotBlank(checkout)){
            checkout_int = Integer.valueOf(checkout);
        }
        List<String> states = new ArrayList<>();
        if(ObjectUtils.isNotNull(state)){
            switch (state){
                case "10":
                    states.add("0");
                    states.add("3");
                    break;
                default:
                    states.add(state);
                    break;
            }
        }
        QueryWrapper<AgentDelivery> constant = new QueryWrapper<AgentDelivery>();
        if(StrUtil.isNotBlank(state) && "10".equals(state)){
            constant.eq("create_user_id", params.get("userId"));
            constant.apply("DATE(create_time) = DATE({0})", new Date());
        }
        constant
        .between(StringUtils.isNotBlank(startTime), "order_time", startTime, endTime)
        .in(CollectionUtil.isNotEmpty(states), "state", states)
        .eq(ObjectUtils.isNotEmpty(params.get("agentId")), "agent_id", params.get("agentId"))
        .eq(ObjectUtils.isNotEmpty(checkout_int), "checkout", checkout_int)
                .eq(ObjectUtils.isNotNull(regionId), "region_id", regionId)
                .like(StringUtils.isNotBlank(docNo), "doc_no", docNo)
        .last("order by state, order_time desc, create_time desc, agent_id");

        IPage<AgentDelivery> page = this.page(
                new Query<AgentDelivery>().getPage(params),
                constant
        );

        return new PageUtils(page);
    }

    /**
     * 入库代办交货列表查询统计
     * @param params
     * @return
     */
    @Override
    public Map<String, Object> queryPageStatistics(Map<String, Object> params) {
        String docNo = (String)params.get("docNo");
        String state = (String)params.get("state");
        Object regionId = params.get("regionId");
        String startTime = (String)params.get("startTime");
        String endTime = (String)params.get("endTime");
        // 结账状态
        String checkout = (String)params.get("checkout");
        Integer checkout_int = null;
        if (StringUtils.isNotBlank(checkout)){
            checkout_int = Integer.valueOf(checkout);
        }
        List<String> states = new ArrayList<>();
        if(ObjectUtils.isNotNull(state)){
            switch (state){
                case "10":
                    states.add("0");
                    states.add("3");
                    break;
                default:
                    states.add(state);
                    break;
            }
        }
        QueryWrapper<AgentDelivery> constant = new QueryWrapper<AgentDelivery>();
        if(StrUtil.isNotBlank(state) && "10".equals(state)){
            constant.eq("create_user_id", params.get("userId"));
            constant.apply("DATE(create_time) = DATE({0})", new Date());
        }
        constant
        .between(StringUtils.isNotBlank(startTime), "order_time", startTime, endTime)
        .in(CollectionUtil.isNotEmpty(states), "state", states)
        .eq(ObjectUtils.isNotEmpty(params.get("agentId")), "agent_id", params.get("agentId"))
        .eq(ObjectUtils.isNotEmpty(checkout_int), "checkout", checkout_int)
                .eq(ObjectUtils.isNotNull(regionId), "region_id", regionId)
                .like(StringUtils.isNotBlank(docNo), "doc_no", docNo);
        
        // 使用数据库聚合函数进行统计，提高效率
        Map<String, Object> statistics = baseMapper.queryPageStatistics(constant);
        if (statistics == null) {
            statistics = new HashMap<>();
            statistics.put("totalMoney", BigDecimal.ZERO);
            statistics.put("totalNumber", 0);
            statistics.put("totalWeight", BigDecimal.ZERO);
            statistics.put("totalDiscount", BigDecimal.ZERO);
            statistics.put("totalPremium", BigDecimal.ZERO);
        }
        
        return statistics;
    }

    /**
     * 入库代办交货总表查询
     * @param po
     * @return
     */
    @Override
    public Map<String, Object> sequence(AgentDeliverySequencePO po) {
        Map<String, Object> result = new HashMap<>();
        IPage iPage = new Page(po.getPage(), po.getLimit());
        IPage<AgentDeliveryDetailVO> page = baseMapper.sequence(iPage, po);
        Map<String, Object> sta = baseMapper.sequenceSta(po);
        List<AgentDeliveryDetailVO> records = page.getRecords();
        if(CollectionUtil.isNotEmpty(records)){
            for(AgentDeliveryDetailVO record : records){
                QueryWrapper<AgentDeliveryDetailPack> packQueryWrapper = new QueryWrapper();
                packQueryWrapper.in("detail_id", record.getId());
                List<AgentDeliveryDetailPack> detailPacks = detailPackService.getBaseMapper().selectList(packQueryWrapper);
                if(CollectionUtil.isNotEmpty(detailPacks)){
                    try {
                        record.setPackageCostForSales(detailPacks.stream().mapToDouble(flow -> flow.getUnitPrice().doubleValue()).sum());
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    try {
                        record.setPackageCost(detailPacks.stream().filter(r -> r.getMode().equals(0)).mapToDouble(flow -> flow.getUnitPrice().doubleValue()).sum());
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                List<Stock> stocks = stockService.queryStockByDetailIdAndOrderId(record.getDeliveryId(), record.getId());
                if(CollectionUtil.isNotEmpty(stocks)){
                    record.setCostWeight(stocks.get(0).getCostWeight());
                }
            }
        }
        result.put("page", new PageUtils(page));
        result.put("statistics", sta);
        return result;
    }

    /**
     * 详情入库代办交货
     * @param id null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    public R detailAgentDelivery(Long id) {
        AgentDelivery agentDelivery = baseMapper.selectById(id);
        if (agentDelivery == null){
            return R.fail("订单不存在");
        }
        // 查询原订单的其他费用
        log.info("查询原订单的其他费用:{}", agentDelivery.getDocNo());
//        QueryWrapper<OrderCost> orderCostQueryWrapper = new QueryWrapper();
//        orderCostQueryWrapper.eq("main_id", agentDelivery.getId());
        List<OrderCost> orderCosts = orderCostService.selectByMainId(agentDelivery.getId());
        // 查询原订单的商品
//        QueryWrapper<AgentDeliveryDetail> detailQuery = new QueryWrapper();
//        detailQuery.eq("delivery_id", agentDelivery.getId());
        List<AgentDeliveryDetail> details = deliveryDetailService.selectByOrderId(agentDelivery.getId());
        if (CollectionUtils.isNotEmpty(details)){
            Map<Long, Map<Long, BigDecimal>> costMap = new HashMap<>();
            for (AgentDeliveryDetail detail: details) {
//                Products products = productsService.getById(detail.getCommodityId());
//                if(ObjectUtil.isNull(products)){
//                    continue;
//                }
//                detail.setCommodityCode(products.getCommonCode());
                // 查询原订单的商品的包装
                log.info("查询原订单的商品的包装:{}", JSON.toJSONString(detail.getId()));
//                QueryWrapper<AgentDeliveryDetailPack> packQueryWrapper = new QueryWrapper();
//                packQueryWrapper.in("detail_id", detail.getId());
                List<AgentDeliveryDetailPack> detailPacks = detailPackService.selectByDetailId(detail.getId());
                detail.setAutoCosts(detailPacks);

                // 查询原订单的商品的其他费用
                log.info("查询原订单的商品的其他费用:{}", JSON.toJSONString(detail.getId()));
//                QueryWrapper<OrderCost> detailCost = new QueryWrapper();
//                detailCost.in("main_id", detail.getId());
                List<OrderCost> costs = orderCostService.selectByMainId(detail.getId());
                if (CollectionUtils.isNotEmpty(costs)){
                    for (OrderCost cost : costs) {
                        // 不存在map中
                        Map<Long, BigDecimal> map = new HashMap<>();
                        if (costMap.get(cost.getCostClauseId()) != null ){
                            map = costMap.get(cost.getCostClauseId());
                        }
                        map.put(detail.getCommodityId(), detail.getWeight());
                        costMap.put(cost.getCostClauseId(), map);
                    }
                }
                detail.setCosts(costs);
                try {
                    detail.setUnitPackMoney(NumberUtil.div(detail.getPackMoney(), detail.getInNumber()));
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            agentDelivery.setCommodities(details);

            // 赋值费用和商品明细的对应关系
            if (CollectionUtils.isNotEmpty(orderCosts)){
                for (OrderCost cost : orderCosts) {
                    Map<Long, BigDecimal> decimalMap = costMap.get(cost.getCostClauseId());
                    cost.setSerialNumberList(decimalMap);
                }
                agentDelivery.setCosts(orderCosts);
            }
        }
        List<StockFlowDTO> flows = stockFlowService.queryOutFlowByOrderNo(agentDelivery.getDocNo(), agentDelivery.getId());
        agentDelivery.setStockFlows(flows);
        List<Stock> stocks = stockService.queryStockByOrderId(agentDelivery.getId());
        agentDelivery.setStocks(stocks);
        return R.data(agentDelivery);
    }

    /**
     * 新增入库代办交货
     * @param agentDelivery null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<AgentDelivery> saveOrEdit(AgentDelivery agentDelivery) throws Exception{
        // 新增入库代办交货主表
        Set<String> commodityNames = new HashSet();
        if (CollectionUtils.isEmpty(agentDelivery.getCommodities())){
            throw new Exception("商品列表不能为空");
        }
        Integer number = 0;
        BigDecimal weight = BigDecimal.ZERO;
        BigDecimal goodsMoney = BigDecimal.ZERO;
        // 应收待办 = 总合计 - 代加工费 - 其他费用 - 商品的包装(成本 != 代办)的费用
        BigDecimal agentArrears =agentDelivery.getMoney()==null?BigDecimal.ZERO:agentDelivery.getMoney();
        // 班组欠款
        BigDecimal teamArrears = BigDecimal.ZERO;

        agentArrears = agentArrears.subtract(agentDelivery.getTeamMoney()==null?BigDecimal.ZERO:agentDelivery.getTeamMoney());
        BigDecimal weightTotal = BigDecimal.ZERO;
        for (AgentDeliveryDetail deliveryDetail: agentDelivery.getCommodities()) {
            deliveryDetail.setCosts(new ArrayList<>());
            // 去除入库数量，重量逻辑，所以默认为订单的数量，重量的值
            deliveryDetail.setInNumber(deliveryDetail.getNumber());
            deliveryDetail.setInWeight(deliveryDetail.getWeight());
            deliveryDetail.setMoney(BigDecimal.ZERO);
            weightTotal = NumberUtil.add(weightTotal, deliveryDetail.getWeight());
        }
        // 商品id集合
        List<Long> productIds = agentDelivery.getCommodities().stream().map(AgentDeliveryDetail::getCommodityId).collect(Collectors.toList());
//        // 判断商品是否有跨台账的情况
//        QueryWrapper<Products> queryWrapper = new QueryWrapper<>();
//        queryWrapper.in("id", productIds);
//        queryWrapper.groupBy("region_id");
        List<Products> regionCount = productsService.queryListByIds(productIds);
        Map<Integer, List<Products>> listMap = regionCount.stream().collect(Collectors.groupingBy(Products::getRegionId));
        Set<Integer> regionIds = listMap.keySet();
        if(regionIds.size() > 1){
            throw new Exception("商品跨台账，无法正常保存");
        }
        agentDelivery.setRegionId(regionCount.get(0).getRegionId());
        if (CollectionUtils.isNotEmpty(agentDelivery.getCosts())) {
            for (OrderCost cost : agentDelivery.getCosts()) {
                agentArrears = agentArrears.subtract(cost.getMoney());
            }
        }
        shareCost(agentDelivery);
        for (AgentDeliveryDetail deliveryDetail: agentDelivery.getCommodities()) {
            Optional<Products> currentP = regionCount.stream().filter(el -> el.getId().equals(deliveryDetail.getCommodityId())).findAny();
            if(!currentP.isPresent()){
                log.info("通过商品id:{}没有找到该商品，坏了", deliveryDetail.getCommodityId());
                throw new RuntimeException("通过商品id:"+deliveryDetail.getCommodityCode()+"没有找到该商品");
            }
            deliveryDetail.setWeightAdd(currentP.get().getWeightAdd());
            deliveryDetail.setDeliveryId(agentDelivery.getId());
            // 商品正经重量 = 数量*标重
            BigDecimal actWeight = new BigDecimal(deliveryDetail.getNumber()).multiply(deliveryDetail.getStandard());
            BigDecimal lossWeight = deliveryDetail.getWeight().subtract(actWeight);
            // 毛重-正经重量
            deliveryDetail.setLossWeight(lossWeight);
            // 损失成本（损耗 = 单价*损失重量
            if (deliveryDetail.getUnitPrice() != null){
                deliveryDetail.setLossCost(deliveryDetail.getUnitPrice().multiply(lossWeight));
            }
            if ((lossWeight.compareTo(BigDecimal.ZERO) > 0) && (actWeight.compareTo(BigDecimal.ZERO) > 0)){
                deliveryDetail.setLossRate(lossWeight.divide(actWeight, 6, RoundingMode.HALF_UP));
            }

            BigDecimal packMoney = BigDecimal.ZERO;
            commodityNames.add(deliveryDetail.getCommodityName());
            number = number+deliveryDetail.getNumber();
            weight = weight.add(deliveryDetail.getWeight());
            // 暂定单纯商品的金额合计
            goodsMoney = goodsMoney.add(deliveryDetail.getGoodsMoney()==null?BigDecimal.ZERO:deliveryDetail.getGoodsMoney());
            List<AgentDeliveryDetailPack> autoCosts = deliveryDetail.getAutoCosts();
            if (CollectionUtils.isNotEmpty(autoCosts)){
                for (AgentDeliveryDetailPack detailPack:autoCosts) {
                    // 班组
                    if (detailPack.getMode() == 2) {
                        teamArrears = teamArrears.add(detailPack.getMoney());
                    }
                    // 待办
                    if (detailPack.getMode() == 0){
                        agentArrears = agentArrears.subtract(detailPack.getMoney());
                        packMoney = packMoney.add(detailPack.getMoney());
                        deliveryDetail.setPackMoney(packMoney);
                    }
                }
            }
        }
        agentDelivery.setNumber(number);
        agentDelivery.setWeight(weight);
        agentDelivery.setGoodsMoney(goodsMoney);
        agentDelivery.setTeamArrears(teamArrears);
        agentDelivery.setAgentArrears(agentArrears);
        agentDelivery.setCommodityNames(String.join("|", commodityNames));
        agentDelivery.setVerifyMonet(agentDelivery.getMoney());
        if (agentDelivery.getId() == null){
            agentDelivery.setDocNo(CommonConstant.DBJH+ baseMapper.getNextCode());
            agentDelivery.setCreateTime(new Date());
            log.info("新增待办交货开始：{}", JSON.toJSONString(agentDelivery));
            save(agentDelivery);
        }else {
            // 修改主表数据
            log.info("修改待办交货开始：{}", JSON.toJSONString(agentDelivery));
            updateById(agentDelivery);
            // 删除其他费用，商品信息，已经商品下的信息
            deleteMethod(agentDelivery);
        }
        // 入库代办交货主键
        Long mainId = agentDelivery.getId();
        // 保存订单下明细，包装费用，其他费用
        return saveDetailInfo(mainId, agentDelivery);
    }

    private void shareCost(AgentDelivery agentDelivery) {
        log.info("进入shareCost方法");
        try {
            if (CollectionUtils.isNotEmpty(agentDelivery.getCosts())) {
                log.info("订单费用数量: {}", agentDelivery.getCosts().size());
                agentDelivery.getCommodities().forEach(detail -> {
                    detail.setCosts(new ArrayList<>());
                });
                for (OrderCost cost : agentDelivery.getCosts()) {
                    if (CollectionUtil.isNotEmpty(cost.getSerialNumberList())){
                        Map<Long, BigDecimal> numberMap = cost.getSerialNumberList();
                        // 参与分摊的商品重量合计
                        BigDecimal weightTotal = agentDelivery.getCommodities().stream().
                                filter(s -> numberMap.containsKey(s.getCommodityId())).map(s -> s.getWeight()).
                                reduce(BigDecimal.ZERO, BigDecimal::add);
                        if(NumberUtil.equals(weightTotal, BigDecimal.ZERO)){
                            log.error("异常数据分摊{}", JSONObject.toJSONString(agentDelivery));
                            return;
                        }
                        // 均摊的单价费用
                        BigDecimal unitMoney = cost.getMoney().divide(weightTotal, 6, RoundingMode.HALF_UP);
                        for (AgentDeliveryDetail deliveryDetail: agentDelivery.getCommodities()) {
                            // 存在
                            if (numberMap.containsKey(deliveryDetail.getCommodityId())){
                                // 单价*重量= 均摊的金额
                                BigDecimal multiply = unitMoney.multiply(deliveryDetail.getWeight());
    //                            BigDecimal money = deliveryDetail.getMoney();
    //                            money = money.add(multiply);
    //                            deliveryDetail.setMoney(money);
                                // 重新组装商品的其他费用
                                if (CollectionUtils.isNotEmpty(deliveryDetail.getCosts())){
                                    OrderCost cost1 = new OrderCost();
                                    cost1.setCostClauseId(cost.getCostClauseId());
                                    cost1.setCostClauseName(cost.getCostClauseName());
                                    cost1.setMoney(multiply);
                                    deliveryDetail.getCosts().add(cost1);
                                }else {
                                    List<OrderCost> detailCosts = new ArrayList<>();
                                    OrderCost cost1 = new OrderCost();
                                    cost1.setCostClauseId(cost.getCostClauseId());
                                    cost1.setCostClauseName(cost.getCostClauseName());
                                    cost1.setMoney(multiply);
                                    detailCosts.add(cost1);
                                    deliveryDetail.setCosts(detailCosts);
                                }
                            }
                        }
                    }
                }
            } else {
                log.info("订单费用为空");
            }
            log.info("shareCost方法执行完成");
        } catch (Exception e) {
            log.error("shareCost方法执行过程中发生错误", e);
            throw e;
        }
    }


    /**
     * 保存订单下明细，包装费用，其他费用
     * @param mainId
     * @param agentDelivery
     * @return
     */
    private R saveDetailInfo(Long mainId, AgentDelivery agentDelivery){
        BigDecimal price_unit = BigDecimal.ZERO;
        try{
            price_unit = agentDelivery.getMoney().divide(agentDelivery.getWeight(), 2, RoundingMode.HALF_UP);
        }catch (Exception e){
            e.printStackTrace();
        }
        List<OrderCost> costs_all = new ArrayList<>();
        // 保存入库代办交货的其他费用
        log.info("保存入库代办交货的其他费用:{}", JSON.toJSONString(agentDelivery.getDocNo()));
        if (CollectionUtils.isNotEmpty(agentDelivery.getCosts())){
            for (OrderCost cost :agentDelivery.getCosts()) {
                cost.setId(null);
                cost.setMainId(mainId);
                costs_all.add(cost);
            }
        }
        // 保存入库代办交货的商品
        log.info("保存入库代办交货的商品:{}", JSON.toJSONString(agentDelivery.getDocNo()));
        List<AgentDeliveryDetail> commodities = agentDelivery.getCommodities();
        for (AgentDeliveryDetail deliveryDetail: commodities) {
            // 商品金额+商品的其他费用 =总金额
            BigDecimal money = deliveryDetail.getGoodsMoney();
            if (CollectionUtils.isNotEmpty(deliveryDetail.getCosts())){
                for (OrderCost cost :deliveryDetail.getCosts()) {
                    money = money.add(cost.getMoney());
                }
            }
            if (deliveryDetail.getPackMoney() != null){
                money = money.add(deliveryDetail.getPackMoney());
            }
            BigDecimal cost_1= deliveryDetail.getCost()==null?BigDecimal.ZERO:deliveryDetail.getCost();
            BigDecimal multiply = price_unit.multiply(deliveryDetail.getWeight());
            cost_1 = cost_1.add(multiply);
            deliveryDetail.setCost(cost_1);
            BigDecimal money_2= deliveryDetail.getMoney()==null?BigDecimal.ZERO:deliveryDetail.getMoney();
            money_2 = money_2.add(money);
            deliveryDetail.setMoney(money_2);
            deliveryDetail.setDeliveryId(mainId);
            deliveryDetailService.saveOrUpdate(deliveryDetail);
            // 保存入库代办交货的商品包装关系表
            log.info("保存入库代办交货的商品包装关系表:{}", JSON.toJSONString(agentDelivery.getDocNo()));
            if (CollectionUtils.isNotEmpty(deliveryDetail.getAutoCosts())){
                List<AgentDeliveryDetailPack> autoCosts = deliveryDetail.getAutoCosts();
                for (AgentDeliveryDetailPack autoCost: autoCosts) {
                    autoCost.setId(null);
                    autoCost.setNumber(BigDecimal.valueOf(deliveryDetail.getNumber()));
                    autoCost.setDetailId(deliveryDetail.getId());
                }
                detailPackService.saveBatch(autoCosts);
            }
            // 保存入库代办交货的商品的其他费用
            log.info("保存入库代办交货的商品的其他费用:{}", JSON.toJSONString(agentDelivery.getDocNo()));
            if (CollectionUtils.isNotEmpty(deliveryDetail.getCosts())){
                for (OrderCost cost :deliveryDetail.getCosts()) {
                    cost.setId(null);
                    cost.setMainId(deliveryDetail.getId());
                    costs_all.add(cost);
                }
            }
        }
        if (CollectionUtils.isNotEmpty(costs_all)){
            orderCostService.saveBatch(costs_all);
        }
        return R.data(agentDelivery);
    }


    /**
     * 提交入库代办交货
     * @param agentDelivery null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R submitAgentDelivery(AgentDelivery agentDelivery) throws Exception{
//        if (agentDelivery.getOrderStatus().intValue() == 2){
//            throw new Exception("订单已入库，不能操作");
//        }
        Long agentId = agentDelivery.getAgentId();
        QueryWrapper<AgentDelivery> wrapper = new QueryWrapper<>();
        wrapper.eq("agent_id", agentId);
        wrapper.gt("create_time", DateUtils.addMinutes(new Date(), -2));
        List<AgentDelivery> recentAdList = baseMapper.selectList(wrapper);
        if(CollectionUtil.isNotEmpty(recentAdList)){
            return R.fail(agentDelivery.getAgentName()+"最近2分钟内已经添加了代办订单，请稍后再添加");
        }
        agentDelivery.setOrderStatus(2);
        R<AgentDelivery> result = saveOrEdit(agentDelivery);
        if (result.isSuccess()){
            AgentDelivery newDelivery = result.getData();
            // 更新待办,班组的应收金额
//            updateArrears(agentDelivery);
            // 生成代办和班组的往来明细
            saveAccountDetails(agentDelivery);
            //  更新入库库存
            saveInStock(agentDelivery);

            //  更新待办库存
            agentDelivery.setDocNo(newDelivery.getDocNo());
//            saveAgentStock(agentDelivery);
        }

        return R.status(true);
    }

    /**
     * 提交入库代办交货
     * @param agentDelivery null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R currentAgentDelivery(AgentDelivery agentDelivery) throws Exception {
        log.info("进入currentAgentDelivery方法，agentDeliveryId: {}", agentDelivery.getId());
        try {
            // 代办交货主表id
            Long addId = agentDelivery.getId();
            // 原来的代办交货主表
            AgentDelivery oldAD = this.baseMapper.selectById(addId);
            if (oldAD == null) {
                return R.fail("未找到原始订单");
            }
            // 原来的代办交货商品列表
            List<AgentDeliveryDetail> oldADDs = deliveryDetailService.selectByOrderId(addId);

            // 订单时间
            Date orderTime = agentDelivery.getOrderTime();
            // 代办id
            Long agentId = agentDelivery.getAgentId();
            // 代办名字
            String agentName = agentDelivery.getAgentName();
            // 入库单编码
            String docNo = oldAD.getDocNo();
            //
            Long orderId = oldAD.getId();

            shareCost(agentDelivery);

            if (agentDelivery.getCommodities() == null || agentDelivery.getCommodities().isEmpty()) {
                return R.status(true);
            }

            // 新的代办交货商品列表
            for (AgentDeliveryDetail dd : agentDelivery.getCommodities()) {
                try {
                    // 如果详情id是空的，说明是新增。此时正常存储库存
                    if(ObjectUtil.isNull(dd.getId())){
                        deliveryDetailService.saveOrUpdate(dd);
                        saveInStock(orderTime, agentName, docNo, agentId, dd);
                    }else{
                        Optional<AgentDeliveryDetail> optional = oldADDs.stream().filter(o -> o.getId().equals(dd.getId())).findAny();
                        if(optional.isPresent()){
                            // 现有的成本
                            BigDecimal nowCost = calOrderCost(dd);
                            AgentDeliveryDetail oldDetail = optional.get();
                            List<OrderCost> oldOrderCost = orderCostService.selectByMainId(dd.getId());
                            oldDetail.setCosts(oldOrderCost);
                            // 1 判断规格是否发生变化
                            if((ObjectUtil.isNull(dd.getSpecsId()) && ObjectUtil.isNotNull(oldDetail.getSpecsId()) || (ObjectUtil.isNotNull(dd.getSpecsId()) && !dd.getSpecsId().equals(oldDetail.getSpecsId())))){
                                // todo 回收原来的库存
                                stockService.releaseStock(orderId, dd.getId(), agentId, Boolean.TRUE);
                                stockService.releaseStock(orderId, dd.getId(), Constant.WAREHOUSE_ID, Boolean.TRUE);
                                // 如果规格发生变化，正常存储库存
                                saveInStock(orderTime, agentName, docNo, agentId, dd);
                            }else {
                                // 判断入库数量是否发生变化
                                Integer nowInNumber = dd.getNumber();
                                Integer oldInNumber = oldDetail.getNumber();
                                if(nowInNumber == 0 && oldInNumber != 0){
                                    // 回收库存 并且 清空1号仓库的库存
                                    stockService.releaseStock(orderId, dd.getId(), Constant.WAREHOUSE_ID);
                                }else if(nowInNumber != 0 && oldInNumber == 0){
                                    saveInStock(orderTime, agentName, docNo, agentId, dd);
                                }else if(nowInNumber != 0 && oldInNumber != 0 && !NumberUtil.equals(new BigDecimal(nowInNumber), new BigDecimal(oldInNumber))){
                                    // 更新对应库存的 现有数量 及 初始数量。并根据difference是否为负数决定是否回收库存
                                    // 入库数量差额
                                    Integer inNumberDifference = NumberUtil.sub(nowInNumber, oldInNumber).intValue();
                                    // 更新对应库存的 现有数量 及 初始数量。并根据difference是否为负数决定是否回收库存
                                    extracted(orderId, dd, Constant.WAREHOUSE_ID, inNumberDifference);
                                }

                                // 现在的成本单价
                                BigDecimal nowCostWeight = NumberUtil.div(nowCost, getActWeight(dd));
                                // 如果原来的成本单价不等于现在的成本单价，说明成本发生变化。此时更新成本单价
                                stockService.updateStockByDetailId(nowCostWeight, dd.getId(), orderId, dd.getUnitPrice());
                            }

                        }
                    }
                } catch (Exception e) {
                    log.error("处理商品详情时发生错误，detailId: {}", dd.getId(), e);
                    throw e;
                }
            }

            List<Long> oldADDIds = oldADDs.stream().map(o -> o.getId()).collect(Collectors.toList());
            List<Long> newADDIds = agentDelivery.getCommodities().stream().map(o -> o.getId()).collect(Collectors.toList());
            for(Long oldId : oldADDIds){
                if(!newADDIds.contains(oldId)){
                    deliveryDetailService.deleteById(oldId);
                    stockService.releaseStock(orderId, oldId, Constant.WAREHOUSE_ID);
                    stockService.releaseStock(orderId, oldId, agentId);
                }
            }


            R<AgentDelivery> result = saveOrEdit(agentDelivery);
            if (result.isSuccess()){
//                AgentDelivery newDelivery = result.getData();
                // 更新待办,班组的应收金额
    //            updateArrears(agentDelivery);
                // 生成代办和班组的往来明细
                saveAccountDetails(agentDelivery);
                for(AgentDeliveryDetail dd : agentDelivery.getCommodities()){
                    stockService.updatePackageUnitPriceByDetailId(dd.getAutoCosts(), dd.getId(), dd.getDeliveryId());
                }
            }
            return R.status(true);
        } catch (Exception e) {
            log.error("currentAgentDelivery方法执行过程中发生错误", e);
            throw e;
        }
    }


    /**
     *
     * @param orderId 订单id
     * @param dd 最新的详情信息
     * @param warehouseId  存储仓库id
     * @param inNumberDifference 库存数量差额
     * @throws Exception
     */
    private void extracted(Long orderId, AgentDeliveryDetail dd, Long warehouseId, Integer inNumberDifference) throws Exception {
        Stock stock = stockService.queryStockByDetailIdAndOrderIdAndWarehouseId(orderId, dd.getId(), warehouseId);
        if(inNumberDifference > 0){
            // 多了 直接加就好
            StockUpdatePO upPO = new StockUpdatePO();
            upPO.setId(stock.getId());
            upPO.setNumber(stock.getNumber() + inNumberDifference);
            stockService.updateStock(upPO);
        }else if(inNumberDifference < 0){
            // 少了就需要判断少了多少，是否剩余的数量无法补齐。如果补不起，则需要把库存回收
            if((stock.getNumber() + inNumberDifference) >= 0){
                StockUpdatePO upPO = new StockUpdatePO();
                upPO.setId(stock.getId());
                upPO.setNumber(stock.getNumber() + inNumberDifference);
                stockService.updateStock(upPO);
            }else{
                // 1. 释放占用的库存
                stockService.releaseStock(stock);
                // 2.
                Stock stock2 = stockService.queryStockByDetailIdAndOrderIdAndWarehouseId(orderId, dd.getId(), warehouseId);
                StockUpdatePO upPO2 = new StockUpdatePO();
                upPO2.setId(stock.getId());
                upPO2.setNumber(stock2.getNumber() + inNumberDifference);
                stockService.updateStock(upPO2);
            }
        }
    }

    /**
     * 更新待办,班组的应收金额
     *
     * @param agentDelivery null
     * @return void
     * @author wrj
     * @since 2024/3/22 上午11:47
     */
    private void updateArrears(AgentDelivery agentDelivery){
        // 更新待办的应收金额
        AddressBook addressBook = addressBookService.getById(agentDelivery.getAgentId());
        BigDecimal arrears = addressBook.getArrears();
        // 加上该订单代办应收金额
        arrears = arrears.add(agentDelivery.getAgentArrears());
        addressBook.setArrears(arrears);
        addressBookService.updateById(addressBook);

        // 班组欠款
        if (agentDelivery.getTeamId() != null){
            // 更新待办的应收金额
            AddressBook addressBook_2 = addressBookService.getById(agentDelivery.getTeamId());
            BigDecimal arrears_2 = addressBook_2.getArrears()==null?BigDecimal.ZERO: addressBook_2.getArrears();
            // 加上该订单代办应收金额
            arrears_2 = arrears_2.add(agentDelivery.getTeamArrears());
            addressBook_2.setArrears(arrears_2);
            addressBookService.updateById(addressBook_2);
        }
    }

    /**
     * 更新入库 库存
     * @param newDelivery null
     * @return void
     * @author wrj
     * @since 2024/3/22 上午11:49
     */
    private void saveInStock(AgentDelivery newDelivery) throws Exception {
        // 生成入库库存
        for (AgentDeliveryDetail detail :newDelivery.getCommodities()) {
            // 订单时间
            Date orderTime = newDelivery.getOrderTime();
            // 代办id
            Long agentId = newDelivery.getAgentId();
            // 代办名字
            String agentName = newDelivery.getAgentName();
            // 入库单编码
            String docNo = newDelivery.getDocNo();
            //
            Long orderId = newDelivery.getId();
            saveInStock(orderTime, agentName, docNo, agentId, detail);
        }
    }

    private void saveInStock(Date orderTime, String agentName, String docNo, Long agentId, AgentDeliveryDetail detail) throws Exception {
        // 根据商品id查询商品
        Products products = productsService.getById(detail.getCommodityId());
        if (products == null){
            return;
        }
        List<AgentDeliveryDetailPack> packs = detailPackService.selectByDetailId(detail.getId());
        String packageCost = JSONArray.toJSONString(packs);
        Long specsId = detail.getSpecsId();
        String specsName = null;
        if (ObjectUtil.isNotNull(specsId)){
            ProductSpec productSpec = specService.getById(detail.getSpecsId());
            specsName = productSpec.getName();
        }
        // 录入一号仓库的数量
        int inNumber = detail.getNumber();
        // 商品重量：如果是标品 = 标重 * 数量，如果不是标品 = 毛重
        BigDecimal actWeight = getActWeight(detail);
        // 录入一号仓库的重量
        BigDecimal inWeight = actWeight;
        // 计算成本金额
        BigDecimal add = calOrderCost(detail);
        // 录入一号仓库的货物的货款
        BigDecimal inMoney = add;
        if(inNumber != 0 || !NumberUtil.equals(inWeight, BigDecimal.ZERO)){
            // 通过独立的服务类调用，确保切面能正常工作
            inboundStockService.saveInStock(orderTime, inMoney, products, specsId, specsName, inNumber, inWeight, 0, Constant.WAREHOUSE_ID, Constant.WAREHOUSE_NAME, agentName, packageCost, docNo, detail.getDeliveryId(), detail.getId(), detail.getUnitPrice());
        }
    }

    /**
     * 计算入库成本(蔬菜金额 + 其他金额)
     * @param detail
     * @return
     */
    private BigDecimal calOrderCost(AgentDeliveryDetail detail) {
        BigDecimal otherCost = BigDecimal.ZERO;
        // 商品其他费用
        List<OrderCost> orderCosts = detail.getCosts();
        if(CollectionUtil.isNotEmpty(orderCosts)){
            for(OrderCost oc : orderCosts){
                otherCost = NumberUtil.add(otherCost, oc.getMoney());
            }
        }
        //成本金额 = 蔬菜金额 + 其他金额
        return NumberUtil.add(detail.getGoodsMoney(), otherCost);
    }

    /**
     * 针对非标产品设计
     * 非标产品的净重就是他的毛重
     * @param detail
     * @return
     */
    private BigDecimal getActWeight(AgentDeliveryDetail detail) throws Exception {
        BigDecimal actWeight;
        if(BigDecimal.ZERO.equals(detail.getStandard())){
            actWeight = detail.getWeight();
        }else{
            actWeight = NumberUtil.mul(detail.getStandard(), new BigDecimal(detail.getNumber()));
        }
        return actWeight;
    }

    /**
     * 记录库存
     * @param orderTime
     * @param priceUnit
     * @param product
     * @param specsId
     * @param inNumber
     * @param inWeight
     */
//    private void saveStock(Date orderTime, BigDecimal priceUnit, Products product, Long specsId, Integer inNumber, BigDecimal inWeight, Integer storageType , Long warehouseId, String warehouseName, String agentName, String packageCost) {
//        Stock stock = new Stock();
//        stock.setCommodityId(product.getId());
//        stock.setCommodityName(product.getCommonName());
//        stock.setCommonCode(product.getCommonCode());
//        stock.setCommodityTypeName(product.getCategory());
//        if (ObjectUtil.isNotNull(specsId)){
//            ProductSpec productSpec = specService.getById(specsId);
//            stock.setSpecsName(productSpec.getName());
//            stock.setSpecsId(specsId);
//        }
//        stock.setTag(product.getTags());
//        stock.setStandard(product.getStandardWeight());
//        stock.setOrderTime(orderTime);
//        stock.setNumber(inNumber);
//        stock.setWeight(inWeight);
//        BigDecimal cost = BigDecimal.ZERO;
//        cost = cost.add(priceUnit.multiply(inWeight));
//        stock.setCost(cost);
//        // 成本/重量
//        BigDecimal costWeight = stock.getCost().divide(stock.getWeight(), 2, RoundingMode.HALF_UP);
//        stock.setCostWeight(costWeight);
//        stock.setStorageType(storageType);
//        stock.setWarehouseId(warehouseId);
//        stock.setWarehouseName(warehouseName);
//        stock.setAgentName(agentName);
//        stock.setPackageCost(packageCost);
//        log.info("代办交货商品入库新增库存，新库存：{}", JSON.toJSONString(stock));
//        stockService.save(stock);
//        iStockFlowService.addStockFlow(stock, Constant.StockFlowType.AGENT_IN.getValue(), stock.getNumber(), stock.getNumber(), stock.getStorageOrderNo());
//    }


    /**
     * 更新代办 库存
     * @param agentDelivery null
     * @return void
     * @author wrj
     * @since 2024/3/22 上午11:49
     */
//    private void saveAgentStock(AgentDelivery agentDelivery) {
//        BigDecimal priceUnit = agentDelivery.getMoney().divide(agentDelivery.getWeight(), 2, RoundingMode.HALF_UP);
//
//        // 生成代办库存
//        for (AgentDeliveryDetail detail : agentDelivery.getCommodities()) {
//            // 根据商品id查询商品
//            Products products = productsService.getById(detail.getCommodityId());
//            if (products == null){
//                continue;
//            }
////            QueryWrapper<Stock> stockWrapper = new QueryWrapper<>();
////            // 代办id（仓库id）
////            stockWrapper.lambda().eq(Stock::getWarehouseId, agentDelivery.getAgentId());
////            // 商品id
////            stockWrapper.lambda().eq(Stock::getCommodityId, detail.getCommodityId());
////            // 商品选的规格
////            if (detail.getSpecsId()== null){
////                stockWrapper.lambda().isNull(Stock::getSpecsId);
////            }else {
////                stockWrapper.lambda().eq(Stock::getSpecsId, detail.getSpecsId());
////            }
////            // 订单时间
////            stockWrapper.lambda().eq(Stock::getOrderTime, agentDelivery.getOrderTime());
////            List<Stock> stockList = stockService.getBaseMapper().selectList(stockWrapper);
////            if (CollectionUtils.isNotEmpty(stockList) && stockList.size()>0){
////                Stock stock = stockList.get(0);
////                // 累加到第一条
////                stock.setNumber(stock.getNumber() + detail.getSurplusNumber());
////                BigDecimal weight = stock.getWeight();
////                weight = weight.add(detail.getSurplusWeight());
////                stock.setWeight(weight);
////                BigDecimal cost = stock.getCost();
////                cost = cost.add(priceUnit.multiply(detail.getSurplusWeight()));
////                stock.setCost(cost);
////                // 成本/重量
////                BigDecimal costWeight = stock.getCost().divide(stock.getWeight(), 2, RoundingMode.HALF_UP);
////                stock.setCostWeight(costWeight);
////                log.info("代办交货商品入库更新库存，新库存：{}", JSON.toJSONString(stock));
////                // TODO  增加入库流水
////                stockService.updateById(stock);
////                iStockFlowService.addStockFlow(stock, Constant.StockFlowType.AGENT_IN.getValue(),  stock.getNumber(), stock.getNumber(), stock.getStorageOrderNo());
////            }else {
//                log.info("代办+商品+规格查询商品不存在，则新增");
//                if (detail.getSurplusNumber() > 0){
//                    // TODO 增加入库流水
//                    saveStock(agentDelivery.getOrderTime(), priceUnit, products, detail.getSpecsId(), detail.getSurplusNumber(), detail.getSurplusWeight(), 0, agentDelivery.getAgentId(), agentDelivery.getAgentName(), agentDelivery.getAgentName());
//                }
////            }
//        }
//    }

    /**
     * 新增班组的往来明细
     * @param newDelivery null
     * @return void
     * @author wrj
     * @since 2024/3/22 上午11:44
     */
    private void saveAccountDetails(AgentDelivery newDelivery){
        // 生成代办的往来明细
        AccountDetails accountDetails = new AccountDetails();
        accountDetails.setStaffType(2); // 待办
        accountDetails.setPersonId(newDelivery.getAgentId());
        accountDetails.setDetailType(4); // 交货
        accountDetails.setOrderId(newDelivery.getId());
        accountDetails.setOrderTime(newDelivery.getOrderTime());
        accountDetails.setDocNo(newDelivery.getDocNo());
        accountDetails.setMoney(newDelivery.getAgentArrears());
        log.info("代办交货保存代办的往来明细：{}", JSON.toJSONString(accountDetails));
        QueryWrapper<AccountDetails> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(AccountDetails::getOrderId, newDelivery.getId());
        wrapper.lambda().eq(AccountDetails::getStaffType, 2);
        wrapper.lambda().eq(AccountDetails::getDetailType, 4);
        accountDetailsService.saveOrUpdate(accountDetails, wrapper);
        if (newDelivery.getTeamId() != null){
            AccountDetails accountDetails_2 = new AccountDetails();
            accountDetails_2.setStaffType(3); // 班组
            accountDetails_2.setPersonId(newDelivery.getTeamId());
            accountDetails_2.setDetailType(5); // 加工
            accountDetails_2.setOrderId(newDelivery.getId());
            accountDetails_2.setOrderTime(newDelivery.getOrderTime());
            accountDetails_2.setDocNo(newDelivery.getDocNo());
            accountDetails_2.setMoney(newDelivery.getTeamArrears());
            log.info("代办交货保存班组的往来明细：{}", JSON.toJSONString(accountDetails_2));
            QueryWrapper<AccountDetails> wrapper2 = new QueryWrapper<>();
            wrapper2.lambda().eq(AccountDetails::getOrderId, newDelivery.getId());
            wrapper2.lambda().eq(AccountDetails::getStaffType, 3);
            wrapper2.lambda().eq(AccountDetails::getDetailType, 5);
            accountDetailsService.saveOrUpdate(accountDetails_2);
        }
    }


    /**
     * 删除入库代办交货
     * @param id null
     * @return R
     * @author wrj
     * @since 2024/3/7 下午4:35
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R deleteAgentDelivery(Long id) throws Exception{
        AgentDelivery agentDelivery = baseMapper.selectById(id);
        if (agentDelivery == null){
            throw new Exception("订单不存在");
        }
        baseMapper.deleteById(id);
        // 删除 代办交货商品信息
        deliveryDetailService.deleteByOrderId(id);
        // 删除原订单的其他费用、包装费用
        deleteMethod(agentDelivery);
        // 释放库存
        stockService.releaseStock(agentDelivery.getDocNo());
        return R.status(true);
    }

    /**
     * 批量导入待办交货
     * @param orderList
     * @return
     */
    @Override
    public R uploadAgentDelivery(List<AgentDeliveryImport> orderList) throws Exception {
        Map<String, List<AgentDeliveryImport>> agentMap = orderList.stream().collect(Collectors.groupingBy(AgentDeliveryImport::getAgentName));
        // 验证订单编号是否存在以及是否已经完成
        Set<String> agentNames = agentMap.keySet();
        List<AddressBook> abList = iAddressBookService.queryByNameList(new ArrayList<>(agentNames), 2);
        for(String abName : agentNames){
            AddressBook ab = abList.stream().filter(el -> el.getNoteName().equals(abName)).findAny().orElse(null);
            if(Objects.isNull(ab)){
                return R.fail(abName + "不存在，请检查代办名称是否错误");
            }
        }
        for(AddressBook ab : abList){
//            AgentDelivery ad = selectByDocNo(agentName);
//            if(Objects.isNull(ad)){
//                return R.data(Arrays.asList("订单号" + agentName + "不存在"));
//            }
//            if (ad.getOrderStatus().intValue() == 2){
//                return R.data(Arrays.asList("订单号" + agentName + "已经入库，不可以再次导入"));
//            }
            // 订单编号专成订单ID
            getR(agentMap.get(ab.getNoteName()), ab);
        }
        return R.status(true);
    }

    /**
     * 当日待办交货下商品列表
     * @param agentId null
     * @return List<AgentDeliveryDetailVO>
     * @author wrj
     * @since 2024/7/1 下午8:59
     */
    @Override
    public List<AgentDelivery> todayAgentDelivery(Long agentId, String orderTime) {
        String orderTimeStr;
        if(ObjectUtil.isNull(orderTime)){
            orderTimeStr = DateUtil.today();
        }else{
            orderTimeStr = orderTime;
        }
        log.info("查询{}在{}的采购任务", agentId, orderTimeStr);
        QueryWrapper<AgentDelivery> wrapper = new QueryWrapper<>();
        wrapper.eq("agent_id", agentId);
        wrapper.eq("order_time", orderTimeStr);
        List<AgentDelivery> adList = baseMapper.selectList(wrapper);
        if(CollectionUtil.isNotEmpty(adList)){
            List<Long> adIds = adList.stream().map(BaseEntity::getId).collect(Collectors.toList());
            List<AgentDeliveryDetail> details = deliveryDetailService.selectByOrderIds(adIds);
            for(AgentDelivery ad : adList){
                List<AgentDeliveryDetail> adDetails = details.stream().filter(el -> el.getDeliveryId().equals(ad.getId())).collect(Collectors.toList());
                ad.setCommodities(adDetails);
            }
        }
        return adList;
    }

    @Override
    public List<AgentDeliveryDetail> lastOrder(Long customerId) {
        List<AgentDeliveryDetail> result = new ArrayList<>();
        List<AgentDeliveryDetail> details = new ArrayList<>();
        QueryWrapper<AgentDelivery> detailQuery = new QueryWrapper();
        detailQuery.eq("agent_id", customerId).orderByDesc("create_time").last("limit 1");
        AgentDelivery lastOrder = baseMapper.selectOne(detailQuery);
        if(ObjectUtil.isNotNull(lastOrder)){
            details = deliveryDetailService.selectByOrderId(lastOrder.getId());
        }
        if(CollectionUtil.isNotEmpty(details)){
            // 补充固定损耗
            List<Long> commodityIds = details.stream().map(el -> el.getCommodityId()).collect(Collectors.toList());
            List<Products> productList = productsService.queryListByIds(commodityIds);
            for(AgentDeliveryDetail detail : details){
                Products exist = productList.stream().filter(el -> el.getId().equals(detail.getCommodityId())).findAny().orElse(null);
                if(ObjectUtil.isNotNull(exist)){
                    detail.setWeightAdd(exist.getWeightAdd());
                    result.add(detail);
                }
            }
            // 补充其他费用
            for(AgentDeliveryDetail detail : result){
                List<AgentDeliveryDetailPack> detailPacks = detailPackService.selectByDetailId(detail.getId());
                detail.setAutoCosts(detailPacks);
            }
        }
        return result;
    }

    @Override
    public R preCurrentAgentDelivery(AgentDelivery agentDelivery) throws Exception {
        List<StockFlowDTO> result = new ArrayList<>();
        // 代办交货主表id
        Long addId = agentDelivery.getId();
        // 原来的代办交货主表
        AgentDelivery oldAD = this.baseMapper.selectById(addId);
        // 原来的代办交货商品列表
        List<AgentDeliveryDetail> oldADDs = deliveryDetailService.selectByOrderId(addId);
        // 入库单编码
        String docNo = oldAD.getDocNo();
        shareCost(agentDelivery);
        // 新的代办交货商品列表
        for (AgentDeliveryDetail dd : agentDelivery.getCommodities()) {
            // 如果详情id是空的，说明是新增。此时正常存储库存
            if(ObjectUtil.isNull(dd.getId())){
                log.info("{}-{}-{}-{}-{}, 该商品没有详情id，属于是新增的. 不会影响原来走货", addId, dd.getCommodityId(), dd.getSpecsId(), dd.getNumber(), dd.getWeight());
            }else{
                log.info("{}-{}-{}-{}-{}, 该商品有详情id，不是新增的，此时可能会影响原来走货方向", addId, dd.getCommodityId(), dd.getSpecsId(), dd.getNumber(), dd.getWeight());
                Optional<AgentDeliveryDetail> optional = oldADDs.stream().filter(o -> o.getId().equals(dd.getId())).findAny();
                if(optional.isPresent()){
                    AgentDeliveryDetail oldDetail = optional.get();
                    List<OrderCost> oldOrderCost = orderCostService.selectByMainId(dd.getId());
                    oldDetail.setCosts(oldOrderCost);
                    // 1 判断规格是否发生变化
                    if((ObjectUtil.isNull(dd.getSpecsId()) && ObjectUtil.isNotNull(oldDetail.getSpecsId()) || (ObjectUtil.isNotNull(dd.getSpecsId()) && !dd.getSpecsId().equals(oldDetail.getSpecsId())))){
                        log.info("{}-{}-{}-{}-{}, 规格发生变化了！", addId, dd.getCommodityId(), dd.getSpecsId(), dd.getNumber(), dd.getWeight());
                        List<StockFlowDTO> flowDTOS = stockFlowService.queryOutFlowByOrderNo(docNo, addId, dd.getId());
                    }else {
                        log.info("{}-{}-{}-{}-{}, 规格没有发生变化！", addId, dd.getCommodityId(), dd.getSpecsId(), dd.getNumber(), dd.getWeight());
                        // 判断入库数量是否发生变化
                        Integer nowInNumber = dd.getNumber();
                        Integer oldInNumber = oldDetail.getNumber();
                        if(nowInNumber == 0 && oldInNumber != 0){
                            log.info("{}-{}-{}-{}-{}, 注意：新入库数量是0 原入库数量不是0！", addId, dd.getCommodityId(), dd.getSpecsId(), nowInNumber, oldInNumber);
                            // 回收库存 并且 清空1号仓库的库存
                            List<StockFlowDTO> flowDTOS = stockFlowService.queryOutFlowByOrderNo(docNo, addId, dd.getId());
                        }else if(nowInNumber != 0 && oldInNumber == 0){
                            log.info("{}-{}-{}-{}-{}, 注意：新入库数量不是0 原入库数量是0！", addId, dd.getCommodityId(), dd.getSpecsId(), nowInNumber, oldInNumber);
                            List<StockFlowDTO> flowDTOS = stockFlowService.queryOutFlowByOrderNo(docNo, addId, dd.getId());
                        }else if(nowInNumber != 0 && oldInNumber != 0 && !NumberUtil.equals(new BigDecimal(nowInNumber), new BigDecimal(oldInNumber))){
                            log.info("{}-{}-{}-{}-{}, 注意：新入库数量与原入库数量不同！", addId, dd.getCommodityId(), dd.getSpecsId(), nowInNumber, oldInNumber);
                            // 更新对应库存的 现有数量 及 初始数量。并根据difference是否为负数决定是否回收库存
                            // 入库数量差额
                            Integer inNumberDifference = NumberUtil.sub(nowInNumber, oldInNumber).intValue();
                            List<StockFlowDTO> flowDTOS = stockFlowService.queryOutFlowByOrderNo(docNo, addId, dd.getId());
                        }
                    }
                }else{
                    log.info("找不到:{}？不可能。哪个孙子删了", dd.getId());
                }
            }
        }
        return R.data(result);
    }

    @Override
    public R<AgentDelivery> confirm(AgentDelivery agentDelivery) throws Exception {
        return saveOrEdit(agentDelivery);
    }

    private void getR(List<AgentDeliveryImport> orderList, AddressBook addressBook) throws Exception {
        // 导入订单数据
        AgentDelivery order = new AgentDelivery();
        try {
            Date orderTime = HSSFDateUtil.getJavaDate(Double.parseDouble(orderList.get(0).getDate()));
            order.setOrderTime(orderTime);
        }catch (Exception e){
            throw new RuntimeException("日期格式错误，请检查后重试");
        }
        // 总金额
        BigDecimal money = BigDecimal.ZERO;
        // 验证商品是否存在
        List<AgentDeliveryDetail> commodities = new ArrayList<>();
        for(AgentDeliveryImport anImport : orderList){
            Products product = productsService.queryByCommonCode(anImport.getCommodityCode());
            if(Objects.isNull(product)){
                String failReason = "商品编码《" + anImport.getCommodityCode() + "》不存在";
                throw new RuntimeException(failReason);
            }else{
                //
//                anImport.setWeight(product.getStandardWeight());
                anImport.setPackMoney(NumberUtil.mul(anImport.getBagPrice(), anImport.getNumber()));
                ProductSpec spec = new ProductSpec();
                if(StringUtils.isNotBlank(anImport.getSpecsName())){
                    // 验证商品规格是否存在
                    spec = specService.queryByProductId(product.getId().toString(), anImport.getSpecsName());
                }
                if(Objects.isNull(spec)){
                    String failReason = "商品规格《" + anImport.getSpecsName() + "》不存在";
                    throw new RuntimeException(failReason);
                }else{
                    // 根据商品+规格查询对应订单下是否有商品
                    AgentDeliveryDetail detail = new AgentDeliveryDetail();
                    detail.setPlanNumber(anImport.getNumber());
                    detail.setPlanWeight(anImport.getWeight());
                    detail.setCommodityId(product.getId());
                    detail.setCommodityCode(product.getCommonCode());
                    detail.setCommodityName(product.getCommonName());
                    detail.setSpecsId(spec.getId());
                    detail.setSpecsName(spec.getName());
                    detail.setStandard(product.getStandardWeight());
                    detail.setUnitPrice(anImport.getUnitPrice());
                    detail.setNumber(anImport.getNumber());
                    detail.setWeight(anImport.getWeight());
                    detail.setInNumber(0);
                    detail.setInWeight(BigDecimal.ZERO);
                    detail.setActWeight(anImport.getActWeight());
                    detail.setLossCost(anImport.getLossCost());
                    detail.setLossWeight(anImport.getLossWeight());
                    if (StringUtils.isNotBlank(anImport.getLossRate())){
                        String lossRate = anImport.getLossRate().replace("%","");
                        detail.setLossRate(new BigDecimal(lossRate));
                    }
                    // 计算蔬菜金额 =  商品毛重 * 单价
                    BigDecimal goodsMoney = anImport.getUnitPrice().multiply(anImport.getWeight());
                    detail.setGoodsMoney(goodsMoney);
                    detail.setPackMoney(anImport.getPackMoney());
                    money = money.add(anImport.getMoney()==null?BigDecimal.ZERO:anImport.getMoney());

//                    List<AgentDeliveryDetailPack> autoCosts = new ArrayList<>();
//                    if (anImport.getBagPrice() != null){
//                        AgentDeliveryDetailPack pack = new AgentDeliveryDetailPack();
//                        // TODO 组装一条包装费用
//                        pack.setCostClauseId(50L);
//                        pack.setCostClauseName("泡沫箱（3＃）");
//                        pack.setMode(0);
//                        pack.setUnitPrice(anImport.getBagPrice());
//                        pack.setMoney(anImport.getPackMoney());
//                        autoCosts.add(pack);
//                        detail.setAutoCosts(autoCosts);
//                    }
                    List<ProductCostClause> costClauses = iProductCostClauseService.queryByProducerId(detail.getCommodityId());
                    if(CollectionUtil.isNotEmpty(costClauses)){
                        for(ProductCostClause pcc : costClauses){
                            List<AgentDeliveryDetailPack> autoCosts = new ArrayList<>();
                            AgentDeliveryDetailPack pack = new AgentDeliveryDetailPack();
                            // TODO 组装一条包装费用
                            pack.setCostClauseId(pcc.getCostClauseId());
                            pack.setCostClauseName(pcc.getCostClauseName());
                            pack.setMode(pcc.getMode());
                            pack.setUnitPrice(pcc.getDefaultPrice());
                            pack.setNumber(new BigDecimal(detail.getNumber()));
                            pack.setMoney(NumberUtil.mul(pack.getNumber(), pack.getUnitPrice()));
                            autoCosts.add(pack);
                            detail.setAutoCosts(autoCosts);
                        }

                    }
//                    List<OrderCost> costs = new ArrayList<>();
//                    // 待办费
//                    if (anImport.getCost1() != null){
//                        OrderCost cost_1 = new OrderCost();
//                        cost_1.setCostClauseId(84L);
//                        cost_1.setCostClauseName("代办");
//                        cost_1.setMoney(anImport.getCost1());
//                        costs.add(cost_1);
//                    }
//                    // 装车费
//                    if (anImport.getCost2() != null){
//                        OrderCost cost_2 = new OrderCost();
//                        cost_2.setCostClauseId(66L);
//                        cost_2.setCostClauseName("装车费");
//                        cost_2.setMoney(anImport.getCost2());
//                        costs.add(cost_2);
//                    }
//                    // 运费
//                    if (anImport.getCost3() != null){
//                        OrderCost cost_3 = new OrderCost();
//                        cost_3.setCostClauseId(67L);
//                        cost_3.setCostClauseName("运费");
//                        cost_3.setMoney(anImport.getCost3());
//                        costs.add(cost_3);
//                    }
//                    detail.setCosts(costs);
                    commodities.add(detail);
                }
            }
        }

        order.setMoney(money);
        order.setAgentId(addressBook.getId());
        order.setAgentName(addressBook.getNoteName());
        order.setCommodities(commodities);
        this.saveOrEdit(order);
    }

    /**
     * 查询（未对账金额 > 0）可收款的待办交货
     * @return List<AgentDelivery>
     * @author wrj
     * @since 2024/4/15 下午12:21
     */
    @Override
    public Map<String, Object> canPaymentList(ADCanPayPO po) {
        // 查询原订单的商品
//        QueryWrapper<AgentDelivery> orderQuery = new QueryWrapper();
//        orderQuery.lambda().eq(AgentDelivery::getAgentId, po.getAgentId());
//        orderQuery.lambda().eq(AgentDelivery::getOrderStatus, 2);
//        orderQuery.lambda().in(AgentDelivery::getIsPayFinish, 0, 2);
//        orderQuery.lambda().between(AgentDelivery::getOrderTime, po.getStartTime(), po.getEndTime());
//        List<AgentDelivery> adList = baseMapper.selectList(orderQuery);
        List<AgentDeliveryDetailVO> details = baseMapper.canPaymentList(po);
        List<Map<String, Object>> orderList = new ArrayList<>();
        Set<String> docNoList = new HashSet<>();
        List<String> categoryList = new ArrayList<>();
        for(AgentDeliveryDetailVO add : details){
            if(categoryList.contains(add.getCommodityName())){
                continue;
            }else {
                categoryList.add(add.getCommodityName());
            }
        }
        categoryList.add("全选");
        for(AgentDeliveryDetailVO add : details){
            docNoList.add(add.getDocNo());
        }
        Map<String, List<AgentDeliveryDetailVO>> listMap = details.stream().collect(Collectors.groupingBy(r -> r.getDocNo()));
        for(Map.Entry<String, List<AgentDeliveryDetailVO>> en : listMap.entrySet()){
            Map<String, Object> order = new HashMap<>();
            String docNo = en.getKey();
            List<AgentDeliveryDetailVO> detailVOS = en.getValue();
            BigDecimal moneySum = detailVOS.stream().map(AgentDeliveryDetailVO::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal weightSum = detailVOS.stream().map(AgentDeliveryDetailVO::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal discountSum = detailVOS.stream().map(AgentDeliveryDetailVO::getDiscount).reduce(BigDecimal.ZERO, BigDecimal::add);
            Integer numberSum = detailVOS.stream().mapToInt(AgentDeliveryDetailVO::getNumber).sum();
            Set<String> nameSet = new HashSet();
            for(AgentDeliveryDetailVO detailVO : detailVOS){
                nameSet.add(detailVO.getCommodityName());
            }
            order.put("commodityName", String.join("|", nameSet));
            order.put("agentName", detailVOS.get(0).getAgentName());
            order.put("children", detailVOS);
            order.put("money", detailVOS.get(0).getOrderMoney());
            order.put("docNo", docNo);
            order.put("orderTime", detailVOS.get(0).getOrderTime());
            order.put("number", numberSum);
            order.put("weight", weightSum);
            order.put("actualPay", detailVOS.get(0).getOrderMoney());
            order.put("discount", discountSum);
            order.put("id", detailVOS.get(0).getDeliveryId().toString());
            order.put("remark", detailVOS.get(0).getRemark());
            for(AgentDeliveryDetailVO vo : detailVOS){
                vo.setDocNo("");
                vo.setOrderTime("");
            }
            orderList.add(order);
//            orderList.sort((s1, s2) -> s1.get("orderTime").compareTo(s2.get("orderTime")));
//            orderList.sort(Comparator.comparing(s -> s.get("orderTime")));
            orderList.sort((map1, map2) -> DateUtil.parseDate(map2.get("orderTime").toString()).compareTo( DateUtil.parseDate(map1.get("orderTime").toString())));

        }
        Map<String, Object> result = new HashMap<>();
        result.put("orderList", orderList);
        result.put("categoryList", categoryList);
        result.put("docList", docNoList);
        return result;
    }

    /**
     * 更新 销售订货的下达数据
     * @param id
     * @return
     * @throws Exception
     */
    @Deprecated
    private R updateTransmit(Long id) throws Exception{
        // 删除原订单的商品
        QueryWrapper<AgentDeliveryDetail> detailQuery = new QueryWrapper<>();
        detailQuery.eq("delivery_id", id);
        List<AgentDeliveryDetail> deliveryDetails = deliveryDetailService.getBaseMapper().selectList(detailQuery);
        if (CollectionUtils.isNotEmpty(deliveryDetails)){
            for (AgentDeliveryDetail detail:deliveryDetails) {
                // 订单来源0 为销售订货
                if (detail.getOrderSource().intValue() == 0){
                    QueryWrapper<SalesOrderTransmit> wrapper_tr = new QueryWrapper<>();
                    wrapper_tr.lambda().eq(SalesOrderTransmit::getCommodityId, detail.getCommodityId());
                    if (detail.getSpecsId()== null){
                        wrapper_tr.lambda().isNull(SalesOrderTransmit::getSpecsId);
                    }else {
                        wrapper_tr.lambda().eq(SalesOrderTransmit::getSpecsId, detail.getSpecsId());
                    }
                    SalesOrderTransmit transmit = transmitService.getBaseMapper().selectOne(wrapper_tr);
                    if (transmit != null){
                        transmit.setCompleteNumber(transmit.getCompleteNumber() - detail.getPlanNumber());
                        BigDecimal completeWeight = transmit.getCompleteWeight();
                        completeWeight = completeWeight.subtract(detail.getPlanWeight());
                        transmit.setCompleteWeight(completeWeight);

                        transmit.setSurplusNumber(transmit.getSurplusNumber() + detail.getPlanNumber());
                        // 剩余重量 = 本次重量+已下达重量
                        BigDecimal surplusWeight = transmit.getSurplusWeight();
                        surplusWeight = surplusWeight.add(detail.getPlanWeight());
                        transmit.setSurplusWeight(surplusWeight);
                    }
                    log.info("删除待办交货后，更新已下达数，重量，未下达数，重量：{}", JSON.toJSONString(transmit));
                    transmitService.updateById(transmit);
                }
            }
        }
        return R.status(true);
    }
    /**
     * 删除主方法
     * @param agentDelivery
     * @return
     */
    private R deleteMethod(AgentDelivery agentDelivery) throws Exception {
        // 删除原订单的其他费用
        log.info("删除原订单的其他费用:{}", agentDelivery.getDocNo());
        QueryWrapper<OrderCost> orderCostQueryWrapper = new QueryWrapper();
        orderCostQueryWrapper.eq("main_id", agentDelivery.getId());
        orderCostService.deleteByMainId(agentDelivery.getId());

        // 删除原订单的商品
        QueryWrapper<AgentDeliveryDetail> detailQuery = new QueryWrapper();
        detailQuery.eq("delivery_id", agentDelivery.getId());
        List<AgentDeliveryDetail> deliveryDetails = deliveryDetailService.getBaseMapper().selectList(detailQuery);
        if (CollectionUtils.isNotEmpty(deliveryDetails)){
            // 订单下商品的id集合
            List<Long> detailIds = deliveryDetails.stream().map(AgentDeliveryDetail::getId).collect(Collectors.toList());
            // todo 没有删除订单的商品列表，可能是个隐患
//            log.info("删除订单下的商品列表:{}", JSON.toJSONString(detailIds));
//            QueryWrapper<AgentDeliveryDetail> detailQueryWrapper = new QueryWrapper();
//            detailQueryWrapper.eq("delivery_id", agentDelivery.getId());
//            deliveryDetailService.getBaseMapper().delete(detailQueryWrapper);
            // 删除原订单的商品的包装
            log.info("删除原订单的商品的包装:{}", JSON.toJSONString(detailIds));
//            QueryWrapper<AgentDeliveryDetailPack> packQueryWrapper = new QueryWrapper();
//            packQueryWrapper.in("detail_id", detailIds);
            detailPackService.deleteByDetailId(detailIds, 0);
            // 删除原订单的商品的其他费用
            log.info("删除原订单的商品的其他费用:{}", JSON.toJSONString(detailIds));
            QueryWrapper<OrderCost> detailCost = new QueryWrapper();
            detailCost.in("main_id", detailIds);
            orderCostService.getBaseMapper().delete(detailCost);
        }

        return R.status(true);
    }

    /**
     * 根据订单号查询主标信息
     * @param docNo
     * @return
     */
    AgentDelivery selectByDocNo(String docNo) {
        QueryWrapper<AgentDelivery> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(AgentDelivery::getDocNo, docNo);
        return baseMapper.selectOne(wrapper);
    }
}
